package com.lck.tutor.utils;

import lombok.extern.slf4j.Slf4j;

import java.util.LinkedList;

import static java.lang.Thread.sleep;

@Slf4j
public abstract class Example {

    public static void main(String[] args) {
        QueueMail queue = new QueueMail(2);
        for (int i = 0; i < 3; i++) {
            int id = i;
            new Thread(() -> {
                queue.put(new Message(id, "值" + id));
            }, "生产者" + i).start();
        }
        new Thread(()->{
            while(true){
                try {
                    sleep(1000);
                    queue.take();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"消费者").start();
    }
}

@Slf4j
class QueueMail {
    private LinkedList<Message> list = new LinkedList<>();
    private int capacity;

    QueueMail(int capacity) {
        this.capacity = capacity;
    }

    public Message take() {
        synchronized (list) {
            while (list.isEmpty()) {
                try {
                    log.debug("队列为空, 消费者线程等待");
                    list.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            Message message = (Message) list.removeFirst();
            log.info("消费者消费了一条消息" + message.getId());
            list.notifyAll();
            return message;
        }
    }

    public void put(Message message) {
        synchronized (list) {
            while(list.size() == capacity){
                try {
                    log.debug("队列已满, 生产者线程等待");
                    list.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            list.addLast(message);
            log.info("生产者生产了一条消息" + message.getId());
            list.notifyAll();
        }
    }
}

class Message {
    private int id;
    private String value;

    public Message(int id, String value) {
        this.id = id;
        this.value = value;
    }

    public int getId() {
        return id;
    }

    public String getValue() {
        return value;
    }
}